// GraphSearch3.java
//
// Simple example of using TinkerGraph with Java
// This code builds upon the examples shown in GraphSearch and GraphSearch2
// and adds the findLongestRoute method to the class.
//
// This example does the following:
//   1. Create an empty TinkerGraph instance
//   2. Load the air-routes graph
//   3. Perform some searches against the graph

// I have highlighted any places where the Gremlin is slightly different from the 
// Gremlin we can use in the Gremlin Console.

import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
import org.apache.tinkerpop.gremlin.process.traversal.Path;
import org.apache.tinkerpop.gremlin.process.traversal.*;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.tinkergraph.structure.*;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.util.Gremlin;

import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.Set;

public class GraphSearch3 {
    private TinkerGraph graph;
    private GraphTraversalSource g;

    // Run some tests
    public static void main(String[] args) {
        // If you want to check your Gremlin version, uncomment the next line
        //System.out.println("Gremlin version is: " + Gremlin.version());

        GraphSearch3 gs = new GraphSearch3();
        boolean loaded = gs.loadGraph("air-routes.graphml");

        if (loaded) {
            Map longest = gs.findLongestRoute();
            String s = "The longest route in the graph is between " + longest.get("from");
            s += " and " + longest.get("to") + " covering a distance of ";
            s += longest.get("distance") + " miles.";

            System.out.println(s);

        }
    }

    // Try to create a new graph and load the specified GraphML file
    public boolean loadGraph(String name) {
        graph = TinkerGraph.open();
        g = graph.traversal();

        try {
            g.io(name).read().iterate();
        } catch (IOException e) {
            System.out.println("GraphStats - Air routes GraphML file not found");
            return false;
        }
        return true;
    }

    // Return the distance between two airports.
    // Input parameters are the airport IATA codes.
    // If no route exists between the specified airports return -1
    public Integer getDistance(String from, String to) {
        List result =
                g.V().has("code", from).outE().as("edge").inV().has("code", to).
                      select("edge").by("dist").toList();

        Integer d = ((result.isEmpty()) ? -1 : (Integer) (result.get(0)));

        return (d);
    }

    // Find the distance of the longest route in the graph
    // Returns a map with keys of from,distance and to
    public Map findLongestRoute() {
        // Note how we need to prefix certain things that we would not have to
        // when using the Gremlin console with "__." and "Order."
        Map result =
                g.V().hasLabel("airport").outE("route").
                      order().by("dist", Order.desc).limit(1).
                      project("from", "distance", "to").
                        by(__.inV().values("code")).
                        by("dist").
                        by(__.outV().values("code")).next();

        return (result);
    }
}
